# @FileName  :  auth.py
# @Time      :  2025/8/26 15:19
# @Author    :  Ayanami
# @info      :
from typing import Optional, Union
from tortoise.exceptions import IntegrityError
from app.models.models import User, Teacher, Student, Agent, LoginLog, Dictionary, DictionaryType, Area
from app.schemas.auth import UserRegister, UserType
from app.core.security import get_password_hash, verify_password
from fastapi import HTTPException, status
import secrets
from datetime import datetime, timedelta


class UserCRUD:

    async def get_user_by_username(self, username: str) -> Optional[User]:
        """通过用户名获取用户"""
        return await User.filter(username=username, is_deleted=False).first()

    async def get_user_by_email(self, email: str) -> Optional[User]:
        """通过邮箱获取用户"""
        return await User.filter(email=email, is_deleted=False).first()

    async def get_user_by_phone(self, phone: str) -> Optional[User]:
        """通过手机号获取用户"""
        return await User.filter(phone=phone, is_deleted=False).first()

    async def get_user_by_login_identifier(self, identifier: str) -> Optional[User]:
        """通过登录标识符获取用户（用户名、邮箱或手机号）"""
        user = await User.filter(
            username=identifier, is_deleted=False
        ).first()

        if not user:
            user = await User.filter(
                email=identifier, is_deleted=False
            ).first()

        if not user:
            user = await User.filter(
                phone=identifier, is_deleted=False
            ).first()

        return user

    async def authenticate_user(self, identifier: str, password: str) -> Optional[User]:
        """用户认证"""
        user = await self.get_user_by_login_identifier(identifier)
        if not user:
            return None
        if not verify_password(password, user.password):
            return None
        if not user.is_active:
            return None
        return user

    async def create_user(self, user_data: UserRegister) -> User:
        """创建用户"""
        try:
            # 检查用户名是否已存在
            if await self.get_user_by_username(user_data.username):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="Username already registered"
                )

            # 检查邮箱是否已存在
            if await self.get_user_by_email(user_data.email):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="Email already registered"
                )

            # 检查手机号是否已存在
            if await self.get_user_by_phone(user_data.phone):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="Phone already registered"
                )

            # 创建用户
            user = await User.create(
                username=user_data.username,
                email=user_data.email,
                phone=user_data.phone,
                password=get_password_hash(user_data.password),
                user_type=user_data.user_type,
                is_active=True,
                is_verified=False
            )
            return user

        except IntegrityError as e:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="User creation failed due to data integrity error"
            )

    async def update_last_login(self, user: User):
        """更新最后登录时间"""
        user.last_login = datetime.now()
        user.login_count += 1
        await user.save()

    async def log_login_attempt(self, user_id: Optional[int], login_ip: str,
                                user_agent: str, is_success: bool,
                                failure_reason: Optional[str] = None):
        """记录登录日志"""
        await LoginLog.create(
            user_id=user_id,
            login_ip=login_ip,
            user_agent=user_agent,
            login_type="password",
            is_success=is_success,
            failure_reason=failure_reason
        )

    async def generate_password_reset_token(self, user: User) -> str:
        """生成密码重置令牌"""
        token = secrets.token_urlsafe(32)
        user.password_reset_token = token
        user.token_expires_at = datetime.now() + timedelta(hours=1)  # 1小时过期
        await user.save()
        return token

    async def reset_password_with_token(self, token: str, new_password: str) -> bool:
        """使用令牌重置密码"""
        user = await User.filter(
            password_reset_token=token,
            token_expires_at__gt=datetime.now(),
            is_deleted=False
        ).first()

        if not user:
            return False

        user.password = get_password_hash(new_password)
        user.password_reset_token = None
        user.token_expires_at = None
        await user.save()
        return True

    async def change_password(self, user: User, old_password: str, new_password: str) -> bool:
        """修改密码"""
        if not verify_password(old_password, user.password):
            return False

        user.password = get_password_hash(new_password)
        await user.save()
        return True

    async def get_user_with_details(self, user_id: int) -> Optional[dict]:
        """获取用户详细信息"""
        user = await User.filter(id=user_id, is_deleted=False).first()
        if not user:
            return None

        user_dict = {
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "phone": user.phone,
            "user_type": user.user_type,
            "is_active": user.is_active,
            "is_verified": user.is_verified,
            "created_at": user.created_at.isoformat(),
            "last_login": user.last_login.isoformat() if user.last_login else None,
            "login_count": user.login_count,
            "has_profile": bool(user.teacher_id if user.user_type == UserType.TEACHER
                                else user.student_id if user.user_type == UserType.STUDENT
            else user.agent_id if user.user_type == UserType.ADMIN
            else False)
        }

        # 根据用户类型获取详细信息
        if user.user_type == UserType.TEACHER and user.teacher_id:
            teacher = await Teacher.filter(id=user.teacher_id).first()
            if teacher:
                user_dict["teacher_info"] = {
                    "id": teacher.id,  # 添加id字段
                    "teacher_id": teacher.teacher_id,
                    "name": teacher.name,
                    "specialty": teacher.specialty,
                    "level": teacher.level,
                    "sessions_count": teacher.sessions_count
                }

        elif user.user_type == UserType.STUDENT and user.student_id:
            student = await Student.filter(id=user.student_id).first()
            if student:
                user_dict["student_info"] = {
                    "id": student.id,  # 添加id字段
                    "student_id": student.student_id,
                    "name": student.name,
                    "gender": student.gender,
                    "total_study_hours": student.total_study_hours,
                    "honors_count": student.honors_count
                }

        elif user.user_type == UserType.ADMIN and user.agent_id:
            agent = await Agent.filter(id=user.agent_id).first()
            if agent:
                user_dict["agent_info"] = {
                    "id": agent.id,  # 添加id字段
                    "name": agent.name,
                    "trainee_count": agent.trainee_count,
                    "training_sessions": agent.training_sessions
                }

        return user_dict

# ... existing code ...

# ... existing code ...

    @staticmethod
    async def create_user_profile( user_id: int, profile_data: dict) -> Optional[dict]:
        """为用户创建个人资料并建立关联"""
        user = await User.filter(id=user_id, is_deleted=False).first()
        if not user:
            return None
        try:
            if user.user_type == UserType.TEACHER:
                # 创建教师资料
                teacher = await Teacher.create(**profile_data)
                user.teacher = teacher
                await user.save()
                return {
                    "user_id": user.id,
                    "teacher_id": teacher.id,
                    "profile": {
                        "id": teacher.id,
                        "teacher_id": teacher.teacher_id,
                        "name": teacher.name,
                        "phone": teacher.phone,
                        "id_card": teacher.id_card,
                        "specialty": teacher.specialty,
                        "hire_date": teacher.hire_date.isoformat() if teacher.hire_date else None,
                        "education": teacher.education,
                        "sessions_count": teacher.sessions_count,
                        "level": teacher.level,
                        "notes": teacher.notes,
                        "created_at": teacher.created_at.isoformat() if teacher.created_at else None,
                        "updated_at": teacher.updated_at.isoformat() if teacher.updated_at else None,
                        "email": teacher.email,
                        "is_active": teacher.is_active
                    }
                }

            elif user.user_type == UserType.STUDENT:
                # 创建学生资料
                student = await Student.create(**profile_data)
                user.student = student
                await user.save()
                return {
                    "user_id": user.id,
                    "student_id": student.id,
                    "profile": {
                        "id": student.id,
                        "student_id": student.student_id,
                        "name": student.name,
                        "gender": student.gender.value if student.gender else None,
                        "phone": student.phone,
                        "birthday": student.birthday.isoformat() if student.birthday else None,
                        "id_card": student.id_card,
                        "is_verified": student.is_verified,
                        "wechat": student.wechat,
                        "emergency_contact": student.emergency_contact,
                        "emergency_phone": student.emergency_phone,
                        "work_experience": student.work_experience,
                        "total_study_hours": student.total_study_hours,
                        "honors_count": student.honors_count,
                        "notes": student.notes,
                        "created_at": student.created_at.isoformat() if student.created_at else None,
                        "updated_at": student.updated_at.isoformat() if student.updated_at else None,
                        "email": student.email,
                        "is_active": student.is_active
                    }
                }

            # elif user.user_type == UserType.ADMIN:
            #     # 创建机构资料
            #     agent = await Agent.create(**profile_data)
            #     user.agent = agent
            #     await user.save()
            #     return {
            #         "user_id": user.id,
            #         "agent_id": agent.id,
            #         "profile": agent
            #     }
            return None

        except Exception as e:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Failed to create profile: {str(e)}"
            )

# ... existing code ...



user_crud = UserCRUD()